#include "debug.h"

#include "SDL/SDL.h"

#include "video.h"
#include "videoext.h"

#include "collision.h"
#include "object.h"
#include "draw.h"

#include <stdio.h>

#define LONG(hi,lo) (hi<<16)+lo
#define HI(val) (val<<16)
#define LO(val) val
#define LONGTOWORD LEFTRADIXLONG
#define LEFTRADIXLONG(val) ((val & 0xFFFF0000) >> 16) 
#define SWAPWORD(val) (((val&0x00FF)<<8)+((val&0xFF00)>>8))

long clock;
long timeFrame;
long delayTime;

extern byte v_16x16[];
extern byte vRam[];
extern byte fgRam[];
extern long *infopixels;

#define player objects[0]
extern object* objects;

extern long v_screenposx;
extern long v_screenposy;
extern word v_lookshift;
extern word v_anglebuffer;
extern word FFFFF76A;

extern byte v_jpadhold1;

extern byte *v_collindex;
extern byte CollArray1[];
extern word v_oscillate[];

extern word v_spritequeue[];

char coordstr[25];
char coordstr2[25];
char coordstr3[25];
char coordstr4[25];
char coordstr5[25];
char tileinfo[50];
char tile16info[50];
char joypadinfo[50];
char statusinfo[50];
char renderinfo[50];
char sonicinfo1[50];
char sonicinfox[50];
char sonicinfoy[50];
char sonicinfo2[50];
char sonicinfo3[50];
char screeninfo[50];
char angleinfo[50];
char angleinfo2[50];
char screeninfo2[50];
char tileinfo2[50];
char sensorinfo[50];
char sensorinfo2[50];
char varinfo[50];
char varinfo2[50];
char tilemapinfo[50];
char tilemapinfo2[50];
char tilemapinfo3[50];

char timeinfo[50];
char timeinfo2[50];
char objinfo[50];
char objinfo2[50];
char objinfo3[50];
char objinfo4[50];
char objinfo5[50];
char objinfo6[50];

char selitemtxt[50];

char oscinfo[50];
char oscinfo2[50];
char oscinfo3[50];
char oscinfo4[50];
char oscinfo5[50];
char oscinfo6[50];
char oscinfo7[50];
char oscinfo8[50];
char oscinfo9[50];

char spriteinfo[100][50];

bool mousel, mouser;
int dbgmousex, dbgmousey;
int pfMouseX, pfMouseY;

int eightaddress;

extern bool keys[];
long vRamY=0;

struct menuItem
{
    int x;
    int y;
    int len;
    char text[50];
};

#define NUMITEMS 5
menuItem items[NUMITEMS] = { 
{ 2, 23, 25, "sonic variables" },
{ 2, 24, 25, "object info" },
{ 2, 25, 25, "tile info" },
{ 2, 27, 25, "vram preview" },
{ 2, 26, 25, "misc info" }
};

int selitem=0;

object *oldSelect=(object*)0;

object *selObj;
bool objSel=false;
int objIndex=0;

word oldGfx=0;

extern word *infotext;

bool disableBg=false;
bool disableFg=false;
bool blockmode=false;
bool noscrollx=false;
bool noscrolly=false;

int scrDown = 0;
int delay = 0;

console debug;

//soniclib extended?
void SLX_S1DebugInfo()
{
     debug.setSize(40, 25);
     debug.setMode(1, 1);
     if (keys[SDLK_z]) { disableFg=!disableFg; }
     if (keys[SDLK_x]) { disableBg=!disableBg; }
     if (keys[SDLK_b]) { blockmode=!blockmode; }
     if (keys[SDLK_c]) { noscrollx=!noscrollx; }
     if (keys[SDLK_v]) { noscrolly=!noscrolly; }
     if (keys[SDLK_m]) { debug.scroll(0,1); }
     if (keys[SDLK_n]) { debug.scroll(0,-1); } 
     if (keys[SDLK_f]) { player.X = 0x2502; player.Y = 0x4AC; } 
     if (delay>0) { delay--; }
     if (keys[SDLK_p]) { if (delay==0) { objIndex++; delay=10; } }
     if (keys[SDLK_l]) { if (delay==0) { objIndex--; delay=10; } }
     if (selitem == 1)
     {
         char *_joypadinfo=joypadinfo;
         for (signed int pn=-2; pn<2; pn++)
         {
	     byte n=*((&v_jpadhold1)+pn);
	     unsigned int i = 1 << (sizeof(n) * 8 - 1);
	     while (i > 0) 
	     {
		if (n & i) { *(_joypadinfo++)='1'; }
		else       { *(_joypadinfo++)='0'; }
		i >>= 1;
	     }
             (*_joypadinfo++)=' ';
          }
          char *_statusinfo=statusinfo;          byte n=objects[0].Status;
          unsigned int i = 1 << (sizeof(n) * 8 - 1);
          while (i > 0) 
          {
              if (n & i) { *(_statusinfo++)='1'; }
	      else       { *(_statusinfo++)='0'; }
	      i >>= 1;
          }
          (*_statusinfo++)=' ';
          char *_renderinfo=renderinfo;          n=objects[0].Render;
          i = 1 << (sizeof(n) * 8 - 1);
          while (i > 0) 
          {
              if (n & i) { *(_renderinfo++)='1'; }
	      else       { *(_renderinfo++)='0'; }
	      i >>= 1;
          }
          *(_renderinfo++)=' ';
     
         sprintf(sonicinfox, "X %x  %x  %i.%i", objects[0].X, objects[0].Xdec, objects[0].X, objects[0].ScreenY);
         sprintf(sonicinfoy, "Y %x  %x  %i.%i", objects[0].Y, objects[0].Ydec, objects[0].Y, objects[0].Yfract);
         sprintf(sonicinfo1, "Height %x  Width %x", objects[0].Height, objects[0].Width);
         sprintf(sonicinfo2, "VelX %x VelY %x Inertia %x  ", objects[0].VelocityX, objects[0].VelocityY, objects[0].Inertia);
         sprintf(sonicinfo3, "Angle %x  ", objects[0].Angle);
         sprintf(screeninfo, "Sonic Y distance from center %i", objects[0].Y - LEFTRADIXLONG(v_screenposy) - v_lookshift);
         sprintf(angleinfo, "v_anglebuffer: %d ", (signed char)v_anglebuffer);
         sprintf(angleinfo2, "FFFFF76A: %d ", (signed char)FFFFF76A); 
         sprintf(screeninfo2, "v_screenposx: %x v_screenposy %x", LEFTRADIXLONG(v_screenposx), LEFTRADIXLONG(v_screenposy));
         word *tileunderPtr=FindNearestTile(&objects[0], objects[0].Y+objects[0].Height, objects[0].X+objects[0].Width);
         word tileunder=SWAPWORD(*tileunderPtr);
         sprintf(tileinfo2, "tile under sonic: %x flipx %x flipy %x", (tileunder&0x7FF)*8, (tileunder&0x800)/0x800, (tileunder&0x1000)/0x1000);
         sprintf(varinfo, "invinc: %i spdsho: %i fntang: %i", getobjvariableword(0x30,objects[0]), getobjvariableword(0x32,objects[0]), objects[0].Variables[0x36-0x28]);
         sprintf(varinfo2, "jmping: %i ctllck: %i bckang: %i", objects[0].Variables[0x3C-0x28], getobjvariableword(0x3E,objects[0]), objects[0].Variables[0x37-0x28]);

         signed short sensorL, sensorR;
         signed short floorAngleL;
         signed short floorAngleR;
     
         FindFloor(&objects[0], objects[0].Y+objects[0].Height, objects[0].X-objects[0].Width, 0xD, 0, sensorL, 16, &floorAngleL);
         FindFloor(&objects[0], objects[0].Y+objects[0].Height, objects[0].X+objects[0].Width, 0xD, 0, sensorR, 16, &floorAngleR);
         sprintf(sensorinfo, "sensor L: %i ", sensorL);
         sprintf(sensorinfo2, "sensor R: %i ", sensorR);
         
         DrawText_NoScrollExt(coordstr,25,1,1,infotext);
         DrawText_NoScrollExt(tileinfo,25,1,2,infotext);
         DrawText_NoScrollExt(tile16info,26,1,3,infotext);
         DrawText_NoScrollExt(joypadinfo,45,1,4,infotext);
         DrawText_NoScrollExt(statusinfo,8,1,5,infotext);
         DrawText_NoScrollExt(renderinfo,8,1,6,infotext);
         DrawText_NoScrollExt(sonicinfox,40,1,7,infotext);
         DrawText_NoScrollExt(sonicinfoy,40,1,8,infotext);
         DrawText_NoScrollExt(sonicinfo1,40,1,9,infotext);
         DrawText_NoScrollExt(sonicinfo2,40,1,10,infotext);
         DrawText_NoScrollExt(sonicinfo3,40,1,11,infotext);
         DrawText_NoScrollExt(screeninfo,40,1,12,infotext);
         DrawText_NoScrollExt(angleinfo,40,1,13,infotext);
         DrawText_NoScrollExt(angleinfo2,40,1,14,infotext);
         DrawText_NoScrollExt(screeninfo2,40,1,15,infotext);
         DrawText_NoScrollExt(tileinfo2,40,1,16,infotext);
         DrawText_NoScrollExt(sensorinfo,40,1,17,infotext);
         DrawText_NoScrollExt(sensorinfo2,40,1,18,infotext);
         DrawText_NoScrollExt(varinfo,40,1,19,infotext);
         DrawText_NoScrollExt(varinfo2,40,1,20,infotext);
        
     }
     else if (selitem == 2)
     {
         if (objIndex == 0)
         {
         object *mouseObj = SLX_FindObject(pfMouseX, pfMouseY);

         if (mouseObj != 0) 
         {
             debug.printf("at %i %i object %i", pfMouseX, pfMouseY, selObj-objects);
             if (mousel) { objSel = true;  selObj = mouseObj; }
             printObject(mouseObj, &debug);   
         }
         else
         {
             if (objSel==true) { printObject(selObj, &debug); } 
             if (mousel) { objSel = false;  }
             debug.printf("select an object...");
         }

         
         debug.printf("press p and l to scroll thru");
         debug.printf("all current objects...");
         debug.DrawBuffer_NoScrollExt(1,1,infotext);
         } 
         else
         {
             object *printObj = &objects[objIndex];
                   
             int objcountl=0, objcountr=0;

             for (int c=0; c<128; c++)
             {
                 if (objects[c].ID != 0)
                 {
                     if (objects[c].X < player.X) { objcountl++; }
                     else { objcountr++; }
                 }
             }
             debug.printf("right %i left %i (of sonic)", objcountl, objcountr);
 
             debug.printf("object %i", objIndex);
             if (printObj->ID != 0) 
             printObject(printObj, &debug);
             else
             debug.printf("no object in slot %i", objIndex);
             debug.DrawBuffer_NoScrollExt(1,1,infotext);
         }
         
         
         
     }
     else if (selitem == 3)
     {
         int gameMouseX = dbgmousex/PIXELSIZE;
         int gameMouseY = dbgmousey/PIXELSIZE;

         int nearest8X = gameMouseX - (gameMouseX & 7);
         int nearest8Y = gameMouseY - (gameMouseY & 7);
         int selectScrollX = LEFTRADIXLONG(v_screenposx) & (7);
         int selectScrollY = LEFTRADIXLONG(v_screenposy) & (7);

         selectRegion(nearest8X-selectScrollX, nearest8Y-selectScrollY, 8, 8);
         
         word *tileunderPtr=FindNearestTile(&objects[0], objects[0].Y+objects[0].Height, objects[0].X+objects[0].Width);
         word tileunder=SWAPWORD(*tileunderPtr);
         word tile16=tileunder&0x7FF;
         sprintf(tileinfo2, "tile under sonic: %x flipx %x flipy %x", (tileunder&0x7FF)*8, (tileunder&0x800)/0x800, (tileunder&0x1000)/0x1000);
         
         byte colBlockNum = v_collindex[tile16] & 0xFF; 
         signed short heights[16];
         for (int lp=0; lp<=15; lp++)
              heights[lp] = (signed short)CollArray1[(colBlockNum*16)+lp];//get collision height (grabs height value at X offset for this collision block type)
         sprintf(tilemapinfo, "%2x%2x%2x%2x%2x%2x%2x%2x", heights[0], heights[1], heights[2], heights[3], heights[4], heights[5], heights[6], heights[7]);
         sprintf(tilemapinfo2, "%2x%2x%2x%2x%2x%2x%2x%2x", heights[8], heights[9], heights[10], heights[11], heights[12], heights[13], heights[14], heights[15]);
 
         DrawText_NoScrollExt(tileinfo, 40, 1, 1, infotext);
         DrawText_NoScrollExt(tileinfo2, 40, 1, 2, infotext);
         DrawText_NoScrollExt(coordstr, 40 ,1, 3,infotext);
         DrawText_NoScrollExt(coordstr2 ,40, 1, 4,infotext);
         DrawText_NoScrollExt(coordstr3 ,40,1,5,infotext);
         DrawText_NoScrollExt(coordstr4 ,40,1,6,infotext);
         DrawText_NoScrollExt(coordstr5,40,1,7,infotext);
         DrawText_NoScrollExt(tilemapinfo,40,1,8,infotext);
         DrawText_NoScrollExt(tilemapinfo2,40,1,9,infotext);
         DrawText_NoScrollExt("                     ",40,1,10,infotext);
         DrawText_NoScrollExt("                     ",40,1,11,infotext);
         DrawText_NoScrollExt("                     ",40,1,12,infotext);
         DrawText_NoScrollExt("                     ",40,1,13,infotext);
         DrawText_NoScrollExt("                     ",40,1,14,infotext);
         DrawText_NoScrollExt("                     ",40,1,15,infotext);
         DrawText_NoScrollExt("                     ",40,1,16,infotext);
         DrawText_NoScrollExt("                     ",40,1,17,infotext);
         DrawText_NoScrollExt("                     ",40,1,18,infotext);

         tileToPixelBuf(eightaddress, 8*10, 8*10, infopixels, INFOWIDTH,  INFOHEIGHT);
     }
     else if (selitem == 4)
     {
         if (keys[SDLK_8]) { vRamY -= 16; }
         else if (keys[SDLK_2]) { vRamY += 16; }
         DrawText_NoScrollExt("                     ",40,1,1,infotext);
         DrawText_NoScrollExt("                     ",40,1,2,infotext);
         DrawText_NoScrollExt("                     ",40,1,3,infotext);
         DrawText_NoScrollExt("                     ",40,1,4,infotext);
         DrawText_NoScrollExt("                     ",40,1,5,infotext);
         DrawText_NoScrollExt("                     ",40,1,6,infotext);
         DrawText_NoScrollExt("                     ",40,1,7,infotext);
         DrawText_NoScrollExt("                     ",40,1,8,infotext);
         DrawText_NoScrollExt("                     ",40,1,9,infotext);
         DrawText_NoScrollExt("                     ",40,1,10,infotext);
         DrawText_NoScrollExt("                     ",40,1,11,infotext);
         DrawText_NoScrollExt("                     ",40,1,12,infotext);
         DrawText_NoScrollExt("                     ",40,1,13,infotext);
         DrawText_NoScrollExt("                     ",40,1,14,infotext);
         DrawText_NoScrollExt("                     ",40,1,15,infotext);
         DrawText_NoScrollExt("                     ",40,1,16,infotext);
         DrawText_NoScrollExt("                     ",40,1,17,infotext);
         DrawText_NoScrollExt("                     ",40,1,18,infotext);
         vRamToPixelBuf(vRamY, 16, 16, 8, 8, infopixels, INFOWIDTH, INFOHEIGHT);
       
     }
     else if (selitem == 5)
     {
          /*char *_oscinfo=oscinfo9;          word n=v_oscillate[0];
          int i = 1 << (sizeof(n) * 8 - 1);
          while (i > 0) 
          {
              if (n & i) { *(_oscinfo++)='1'; }
	      else       { *(_oscinfo++)='0'; }
	      i >>= 1;
          }
          *(_oscinfo++)=' ';

         sprintf(oscinfo, "1 %2x %2x 2 %2x %2x", v_oscillate[1], v_oscillate[2], v_oscillate[3], v_oscillate[4]);
         sprintf(oscinfo2, "3 %2x %2x 4 %2x %2x", v_oscillate[5], v_oscillate[6], v_oscillate[7], v_oscillate[8]);
         sprintf(oscinfo3, "5 %2x %2x 6 %2x %2x", v_oscillate[9], v_oscillate[10], v_oscillate[11], v_oscillate[12]);
         sprintf(oscinfo4, "7 %2x %2x 8 %2x %2x", v_oscillate[13], v_oscillate[14], v_oscillate[15], v_oscillate[16]);
         sprintf(oscinfo5, "9 %2x %2x 10 %2x %2x", v_oscillate[17], v_oscillate[18], v_oscillate[19], v_oscillate[20]);
         sprintf(oscinfo6, "11 %2x %2x 12 %2x %2x", v_oscillate[21], v_oscillate[22], v_oscillate[23], v_oscillate[24]);
         sprintf(oscinfo7, "13 %2x %2x 14 %2x %2x", v_oscillate[25], v_oscillate[26], v_oscillate[27], v_oscillate[28]);
         sprintf(oscinfo8, "15 %2x %2x 16 %2x %2x", v_oscillate[29], v_oscillate[30], v_oscillate[31], v_oscillate[32]);

         
         DrawText_NoScrollExt("oscillating values:",40,1,1,infotext);
         DrawText_NoScrollExt(oscinfo,40,1,2,infotext);
         DrawText_NoScrollExt(oscinfo2,40,1,3,infotext);
         DrawText_NoScrollExt(oscinfo3,40,1,4,infotext);
         DrawText_NoScrollExt(oscinfo4,40,1,5,infotext);
         DrawText_NoScrollExt(oscinfo5,40,1,6,infotext);
         DrawText_NoScrollExt(oscinfo6,40,1,7,infotext);
         DrawText_NoScrollExt(oscinfo7,40,1,8,infotext);
         DrawText_NoScrollExt(oscinfo8,40,1,9,infotext);
        
         DrawText_NoScrollExt(oscinfo9,40,1,10,infotext);
         DrawText_NoScrollExt("                     ",40,1,11,infotext);
         DrawText_NoScrollExt("                     ",40,1,12,infotext);
         DrawText_NoScrollExt("                     ",40,1,13,infotext);
         DrawText_NoScrollExt("                     ",40,1,14,infotext);
         DrawText_NoScrollExt("                     ",40,1,15,infotext);
         DrawText_NoScrollExt("                     ",40,1,16,infotext);
         DrawText_NoScrollExt("                     ",40,1,17,infotext);
         DrawText_NoScrollExt("                     ",40,1,18,infotext);*/

         int lsize = 64;
         int line = 0;
         int maxlines=80;
         for (int l=0; l<maxlines; l++)
             sprintf(spriteinfo[l], "                              ");

         for (int plevel=0; plevel<=7; plevel++)
         {
             int numSprites = v_spritequeue[(plevel*lsize)];
             //sprintf(spriteinfo[line++], "pr %i count %i              ", plevel+1, numSprites);
             debug.printf("pr %i count %i              ", plevel+1, numSprites);
             //sprintf(spriteinfo[line++], "----------------------------");
             debug.printf("----------------------------");

             for (int lp=0; lp<numSprites; lp++)
             {
                 int object = v_spritequeue[(plevel*lsize)+1+lp];
                 //sprintf(spriteinfo[line++], "object %i        ", object/68);
                 debug.printf("object %i        ", object/68);
             }
             //sprintf(spriteinfo[line++], "");
             debug.printf("");
         }
         
        
         //for (int lp=0; lp<15; lp++)
         //{
         //    DrawText_NoScrollExt(spriteinfo[lp+scrDown],40,1,1+lp,infotext);
         //}
         debug.DrawBuffer_NoScrollExt(1, 1, infotext);  

         
     }
     sprintf(timeinfo2, "dlt %i", delayTime);
     sprintf(timeinfo, "clk %i frm %i", clock, timeFrame);  
     DrawText_NoScrollExt(items[0].text, items[0].len, items[0].x, items[0].y, infotext);
     DrawText_NoScrollExt(items[1].text, items[1].len, items[1].x, items[1].y, infotext);
     DrawText_NoScrollExt(items[2].text, items[2].len, items[2].x, items[2].y, infotext);
     DrawText_NoScrollExt(items[3].text, items[3].len, items[3].x, items[3].y, infotext);
     DrawText_NoScrollExt(items[4].text, items[4].len, items[4].x, items[4].y, infotext);
     DrawText_NoScrollExt(timeinfo, 25, 2, 22, infotext);
     DrawText_NoScrollExt(timeinfo2, 25, 2, 21, infotext);
}


void SLX_UpdateMouse(int _mousex, int _mousey)
{
    dbgmousex = _mousex;
    dbgmousey = _mousey;

    pfMouseX = (dbgmousex/PIXELSIZE) + LEFTRADIXLONG(v_screenposx);     //playfield mouse x    (relative to v_screenposx)
    pfMouseY = (dbgmousey/PIXELSIZE) + LEFTRADIXLONG(v_screenposy);     //playfield mouse y    (relative to v_screenposy)

    int tilex = (dbgmousex/PIXELSIZE)/TILEW;
    int tiley = (dbgmousey/PIXELSIZE)/TILEH;
    int scrolledX = LEFTRADIXLONG(getHScroll(tiley*8));
    int scrolledY = LEFTRADIXLONG(getVScroll());
    
    int tileScrolledX = (scrolledX/8)%64;
    int tileScrolledY = (scrolledY/8)%64;
    
    int tileOffsetX = (tilex - tileScrolledX) % 64;
    int tileOffsetY = (tiley - tileScrolledY) % 64;

    sprintf(coordstr, "MOUSEX %i MOUSEY %i", dbgmousex, dbgmousey);
    sprintf(coordstr2, "PMOUSX %i PMOUSY %i", pfMouseX, pfMouseY);
    sprintf(coordstr3, "tilex %i tiley %i", tilex, tiley);
    sprintf(coordstr4, "scrolled %i %i", scrolledX, scrolledY);
    sprintf(coordstr5, "tilewise %i %i", tileScrolledX, tileScrolledY); 
    

    word *sixteen=DrawBlocks(&v_screenposx,dbgmousey/PIXELSIZE,dbgmousex/PIXELSIZE,0);
    long sixteenaddress=(long)sixteen;
    
    int eightin16=(tilex%2)+((tiley%2)*2);
    eightaddress=SWAPWORD(sixteen[eightin16]);
    //word flipx=(fgRamVal&0x800)>>11;
    //word flipy=(fgRamVal&0x1000)>>12;
    //word line=(fgRamVal&0x6000)>>13;
    //word priority=(fgRamVal&0x8000)>>15;
    word tileindex=(eightaddress&0x7FF);    


    sprintf(tileinfo, "CURRENT 8 BY 8 %i", tileindex);
    
    //sprintf(tile16info, "CURRENT 16 BY 16 %04X", (sixteenaddress-(int)currentZone.v_16x16));
    sprintf(tile16info, "CURRENT 16 %04X", (sixteenaddress-(int)&v_16x16));

    //

    SLX_CheckSelectText();

    
}

void SLX_UpdateMouseClick(bool left, bool right)
{
    mousel = left;
    mouser = right;

    SLX_CheckSelectText();
}


void SLX_CheckSelectText()
{
    //grab mouse position relative to extended window
    int mousexExt = dbgmousex - DISPLAYWIDTH;
    int mouseyExt = dbgmousey;
 
    
    bool itemSelected = false;
    if (mousel)
    {
        for (int lp=0; lp<NUMITEMS; lp++)
        {
            int itemL = (items[lp].x * 8 * PIXELSIZE);
            int itemR = itemL + (items[lp].len*8*PIXELSIZE);
            if ((mousexExt >= itemL) && (mousexExt <= itemR))
            {
                int itemT = items[lp].y * 8*PIXELSIZE;
                int itemB = itemT + (8*PIXELSIZE);
                if ((mouseyExt >= itemT) && (mouseyExt <= itemB))
                {
                    selitem = lp+1;
                    itemSelected = true;
                }
            }
            
        }
        if (!itemSelected) { /*selitem = 0;*/ }
    }
    
    
}


object *SLX_FindObject(int x, int y)
{
    object *curObj;
    for (int count = 0; count <= 0x7F; count++)
    {
        curObj = &objects[count];

        int width, height;
        if ( ((width = curObj->Width) == 0) || ((height = curObj->Height) == 0) )
            width = curObj->ActionWidth; height = width;

        int objL = curObj->X - width;
        int objR = curObj->X + width;
        int objT = curObj->Y - height;
        int objB = curObj->Y + height;

        if ((x > objL) && (x < objR) && (y > objT) && (y < objB))
            return curObj;
    }

    return 0;
}

void printObject(object *obj, console *c)
{
        

    c->printf("Object ID: %i", obj->ID);
    c->printf("----------------------------");
    c->printf("Subtype: %i", obj->Subtype);
    c->printf("Routine: %i", obj->Routine);
    c->printf("Second Routine: %i", obj->secondRoutine);
    
     
    c->printf("Status flags: %s", getBits(obj->Status));
    c->printf("Render flags: %s", getBits(obj->Render));

    c->printf("Respawn Slot: %i", obj->RespawnNo);

    c->printf("X: %i  %x %x", obj->Xdec, obj->X, obj->ScreenY);
    c->printf("Y: %i  %x %x", obj->Ydec, obj->Y, obj->Yfract);
    c->printf("X Velocity: %i  %x", obj->VelocityX,obj->VelocityX);
    c->printf("Y Velocity: %i  %x", obj->VelocityY,obj->VelocityY);
    c->printf("Inertia: %i  %x", obj->Inertia, obj->Inertia);
    c->printf("Angle: %i  %x", obj->Angle, obj->Angle);

    c->printf("Width: %i  %x", obj->Width, obj->Width);
    c->printf("Height: %i  %x", obj->Height, obj->Height);
    c->printf("Priority: %i  %x", obj->Priority, obj->Priority);
    c->printf("Action Width: %i  %x", obj->ActionWidth, obj->ActionWidth);
    c->printf("Current Mapping Frame: %i  %x", obj->Frame, obj->Frame);
    c->printf("");
    c->printf("Animation");
    c->printf("----------------------------");
    c->printf("Current Animation: %i  %x", obj->Anim, obj->Anim);
    c->printf("Current Animation Frame: %i  %x", obj->AniFrame, obj->AniFrame);
    c->printf("Next Animation Frame: %i  %x", obj->NextAni, obj->NextAni);
    c->printf("Time Frame: %i  %x", obj->TimeFrame, obj->TimeFrame);
    c->printf("Delay Animation: %i  %x", obj->DelayAni, obj->DelayAni);
    c->printf("");
    c->printf("Collision");
    c->printf("----------------------------");
    c->printf("Type: %i  %x", obj->ColType, obj->DelayAni);
    c->printf("Properties: %i  %x", obj->ColProp, obj->ColProp);
    c->printf("");

    c->printf("Variables");
    c->printf("----------------------------");
    c->printf("00  %2x %2x %2x %2x %2x %2x %2x %2x", obj->Variables[0], obj->Variables[1], obj->Variables[2], obj->Variables[3], obj->Variables[4],obj->Variables[5],obj->Variables[6],obj->Variables[7]);
    c->printf("08  %2x %2x %2x %2x %2x %2x %2x %2x", obj->Variables[8], obj->Variables[9], obj->Variables[10], obj->Variables[11], obj->Variables[12],obj->Variables[13],obj->Variables[14],obj->Variables[15]);
    c->printf("10  %2x %2x %2x %2x %2x %2x        ", obj->Variables[16], obj->Variables[17], obj->Variables[18], obj->Variables[19], obj->Variables[20],obj->Variables[21]);
    c->printf("");

    c->printf("Graphics");
    c->printf("----------------------------");
    c->printf("Gfx location: %x", obj->Gfx);
    c->printf("Mappings location: %x", obj->Map);
}    
char *getBits(int n)
{ 
    char bits[10];    char *_bits=bits;          

    int i = 1 << (sizeof(n) * 8 - 1);
    while (i > 0) 
    {
        if (n & i) { *(_bits++)='1'; }
	else       { *(_bits++)='0'; }
	i >>= 1;
    }
    *(_bits++)=' ';
}
void console::setMode(int m, int r)
{
    scrollMode = m;
    renderMode = r;
}

void console::setSize(int w, int h)
{
    displayW = w;
    displayH = h;
}

void console::printf(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    for (int w=0; w<80; w++) { buffer[printLine][w] = ' '; }
    vsprintf(buffer[printLine++], format, args);
    va_end(args); 
}

void console::clear()
{
    for (int h=0; h<CONSOLE_SIZE; h++)
    {
        for (int w=0; w<80; w++) { buffer[h][w] = ' '; }
    }
    printLine = 0;
}

void console::scroll(int x, int y)
{
    scrollX+=x;
    scrollY+=y;
    if (scrollY > CONSOLE_SIZE) { scrollY = CONSOLE_SIZE; }
    if (scrollY < 0) { scrollY = 0; }
}
    
void console::DrawBuffer_NoScrollExt(int x, int y, word *buf)
{
    int top = scrollY;
    int bottom = top + displayH;
    if (bottom > CONSOLE_SIZE) { bottom = CONSOLE_SIZE; }
    int textLine = y;
    for (int line=top; line<bottom; line++)
    {
        DrawText_NoScrollExt(buffer[line], displayW, x, textLine++, buf);
    } 

    if (renderMode == 1) { clear(); }

}

